home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 20 code / Scripting the Finder / Finder Snapshot / Main.cp < prev    next >
Encoding:
Text File  |  1994-10-04  |  9.3 KB  |  378 lines  |  [TEXT/MMCC]

  1. /*================================================================================
  2.     Finder Snapshot
  3.     
  4.     ©1994 Greg Anderson
  5.     greggor@apple.com
  6.     
  7.     A program that records and restores the open Finder windows
  8.         
  9. ================================================================================*/
  10. #include <GestaltEqu.h>
  11. #include <Palettes.h>
  12. #include <TextUtils.h>
  13.  
  14. #include "Main.h"
  15. #include "SaveWindows.h"
  16.  
  17. #include "EventHandler.h"
  18.  
  19. #include "StringUtilities.h"
  20. #include "MacUtilities.h"
  21. #include "AppleEventUtilities.h"
  22.  
  23. #ifndef Exceptions_h
  24. #include "Exceptions.h"
  25. #endif
  26.  
  27. //
  28. // For iuSystemScript
  29. //
  30. #ifndef __PACKAGES__
  31. #include <Packages.h>
  32. #endif
  33.  
  34. //
  35. // For sprintf, strlen
  36. //
  37. #include <stdio.h>
  38. #include <string.h>
  39.  
  40. //
  41. // Prototypes for private functions:
  42. //
  43. void                    InitAll(void);
  44. pascal OSErr            QuitApplicationEvent(TAEvent& ae, TAEvent& reply, long refCon);
  45. pascal OSErr            OpenApplicationEvent(TAEvent& ae, TAEvent& reply, long refCon);
  46. pascal OSErr            OpenDocumentEvent(TAEvent& ae, TAEvent& reply, long refCon);
  47.  
  48. //
  49. // Globals defined in this file:
  50. //
  51. Rect                    gUniverseRect;
  52. RgnHandle                gUniverseRgn = nil;
  53. RgnHandle                gScratchRgn = nil;
  54. GrafPtr                    gWindowMgrPort = nil;
  55.  
  56. SysEnvRec                gThisMacintosh;
  57. Boolean                    gHasAppleEvents;
  58. Boolean                    gApplicationShouldQuit = false;
  59.  
  60. #if USESROUTINEDESCRIPTORS
  61.     static RoutineDescriptor gQuitApplicationHandlerRD    = BUILD_ROUTINE_DESCRIPTOR(uppAEEventHandlerProcInfo, QuitApplicationEvent);
  62.     static RoutineDescriptor gOpenApplicationHandlerRD    = BUILD_ROUTINE_DESCRIPTOR(uppAEEventHandlerProcInfo, OpenApplicationEvent);
  63.     static RoutineDescriptor gOpenDocumentHandlerRD        = BUILD_ROUTINE_DESCRIPTOR(uppAEEventHandlerProcInfo, OpenDocumentEvent);
  64. #endif
  65.  
  66. //----------------------------------------------------------------------------------------
  67. // main: 
  68. //----------------------------------------------------------------------------------------
  69. void main()
  70. {
  71.     RgnHandle        mouseRegion;
  72.     AppFile            theFile;
  73.     DialogPtr        splash;
  74.     short            preLoadFiles;
  75.     short            message;
  76.     short            i;
  77.     OSErr            err = noErr;
  78.     
  79.     //
  80.     // Initialize all of the ToolBox managers, change the cursor
  81.     // shape to a watch and display the splash screen.
  82.     //
  83.     InitAll();
  84.     ChangeCursor(watchCursor);
  85.     
  86.     //
  87.     // Every high-level-event-aware application needs a
  88.     // quit-application handler; otherwise, it won't quit
  89.     // when the machine is shut down (for example)
  90.     //
  91.     // This application quits right away, but heck, we might
  92.     // as well keep this.
  93.     //
  94. #if USESROUTINEDESCRIPTORS
  95.     AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, &gQuitApplicationHandlerRD, 0, false);
  96. #else
  97.     AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, (AEEventHandlerProcPtr) &QuitApplicationEvent, 0, false);
  98. #endif
  99.     
  100.     //
  101.     // We definitely need an open application and
  102.     // an open document handler
  103.     //
  104. #if USESROUTINEDESCRIPTORS
  105.     AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, &gOpenApplicationHandlerRD, 0, false);
  106.     AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, &gOpenDocumentHandlerRD, 0, false);
  107. #else
  108.     AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, (AEEventHandlerProcPtr) &OpenApplicationEvent, 0, false);
  109.     AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, (AEEventHandlerProcPtr) &OpenDocumentEvent, 0, false);
  110. #endif
  111.     
  112.     //
  113.     // Set the cursor back to an arrow
  114.     //
  115.     InitCursor();
  116.     
  117.     //
  118.     // Set up the initial mouse region
  119.     //
  120.     mouseRegion = NewRgn();
  121.     
  122.     //
  123.     // Set up a failure handler for failures that are not
  124.     // trapped elsewhere
  125.     //
  126.     Try
  127.     {
  128.         //
  129.         // Live here until the 'gApplicationShouldQuit' flag
  130.         // becomes true
  131.         //
  132.         while(gApplicationShouldQuit == false)
  133.             HandleEvents(mouseRegion);
  134.     }
  135.     Catch(err)
  136.     {
  137.         //
  138.         // We don't expect to ever get here...
  139.         //
  140.     }
  141. } // main 
  142.  
  143. //----------------------------------------------------------------------------------------
  144. // InitAll: 
  145. // 
  146. // Initialize various Macintosh managers
  147. //----------------------------------------------------------------------------------------
  148. void InitAll()
  149. {
  150.     OSErr    theErr;
  151.     long    heapSpace;
  152.     Ptr        appLimit;
  153.     THz        appBase;
  154.     long    gestaltResult;
  155.     short    callsToMoreMasters = 10;
  156.     
  157.     appBase = ApplicZone();
  158.     appLimit = GetApplLimit();
  159.     heapSpace = FreeMem();
  160.     MaxApplZone();
  161.     appLimit = GetApplLimit();
  162.     heapSpace = FreeMem();
  163.     while( callsToMoreMasters-- )
  164.         MoreMasters();
  165.     
  166.     InitGraf(&qd.thePort);
  167.     InitFonts();
  168.     FlushEvents(everyEvent, 0);
  169.     InitWindows();
  170.     InitMenus();
  171.     TEInit();
  172.     InitDialogs(0L);
  173.     
  174.     //
  175.     // Get the SysEnvirons record
  176.     //
  177.     SysEnvirons( 1, &gThisMacintosh );
  178.  
  179.     //
  180.     // Check to see if AppleEvents are available
  181.     //
  182.     theErr = Gestalt( gestaltAppleEventsAttr, &gestaltResult );
  183.     gHasAppleEvents = ( (theErr == noErr) && ((gestaltResult & (1L << gestaltAppleEventsPresent)) != 0) );
  184.     
  185.     //
  186.     // Set a global rectangle to hold the extent of QuickDraw workspace
  187.     // (Note:  QuickDraw coordinates range from +-32767, but there
  188.     //  are bugs in QuickDraw that make it inadvisable to go beyond
  189.     //  +-16000 or so.)
  190.     //
  191.     SetRect(&gUniverseRect,-16000,-16000,16000,16000);
  192.     gUniverseRgn = NewRgn();
  193.     RectRgn(gUniverseRgn, &gUniverseRect);
  194.     gScratchRgn = NewRgn();
  195.     GetPort(&gWindowMgrPort);
  196. } // InitAll 
  197.  
  198. //----------------------------------------------------------------------------------------
  199. // ExitProgram: 
  200. //----------------------------------------------------------------------------------------
  201. OSErr ExitProgram(CWindowPtr window, short item)
  202. {
  203.     //
  204.     // A "real" program would try to close all of its windows
  205.     // first (give the user a chance to cancel)
  206.     //
  207.     gApplicationShouldQuit = true;
  208.     
  209.     return noErr;
  210. } // ExitProgram 
  211.  
  212. //----------------------------------------------------------------------------------------
  213. // QuitApplicationEvent: 
  214. //----------------------------------------------------------------------------------------
  215. pascal OSErr QuitApplicationEvent(TAEvent& ae, TAEvent& reply, long refCon)
  216. {
  217.     //
  218.     // You should never call ExitToShell from an AppleEvent handler
  219.     //
  220.     gApplicationShouldQuit = true;
  221.     
  222.     return noErr;
  223. } // QuitApplicationEvent
  224.  
  225. //----------------------------------------------------------------------------------------
  226. // MakeAnotherName
  227. //----------------------------------------------------------------------------------------
  228. void MakeAnotherName(FSSpec* newDocument)
  229. {
  230.     short length = newDocument->name[0];
  231.     unsigned char* lastChar = newDocument->name + length;
  232.     long number = 0;
  233.     
  234.     //
  235.     // First extract the number off the end of the name.
  236.     // Not _too_ international friendly, but hey...
  237.     //
  238.     while((*lastChar >= '0') && (*lastChar <= '9') && (length > 0))
  239.     {
  240.         number = (number * 10) + (*lastChar - '0');
  241.         --length;
  242.         --lastChar;
  243.     }
  244.     
  245.     //
  246.     // Also strip off trailing spaces
  247.     //
  248.     while((*lastChar == ' ') && (length > 0))
  249.     {
  250.         --length;
  251.         --lastChar;
  252.     }
  253.     
  254.     //
  255.     // Add one to the number, then append it onto the end
  256.     // with a space.
  257.     //
  258.     ++number;
  259.     ++lastChar;
  260.     ++length;
  261.     *lastChar = ' ';
  262.     
  263.     //
  264.     // It would be a grand idea to check to see if we
  265.     // were about to overwrite the end of the string here,
  266.     // but we don't
  267.     //
  268.     ++lastChar;
  269.     newDocument->name[0] = length;
  270.  
  271.     Str255 numberString;
  272.     NumToString(number, numberString);
  273.     pstrcat(newDocument->name, numberString);
  274. } // MakeAnotherName
  275.  
  276. //----------------------------------------------------------------------------------------
  277. // OpenApplicationEvent: 
  278. //----------------------------------------------------------------------------------------
  279. pascal OSErr OpenApplicationEvent(TAEvent& ae, TAEvent& reply, long refCon)
  280. {
  281.     FSSpec newDocument;
  282.     OSErr err = noErr;
  283.     short refNum = -1;
  284.     Boolean fileOpen = false;
  285.     
  286.     Try
  287.     {
  288.         FSMakeFSSpec(0, 0, "\pUntitled Window Set 1", &newDocument);
  289.  
  290.         //
  291.         // On an open application event, we take a snapshot of all
  292.         // of the open Finder windows and record their positions
  293.         //
  294.         err = dupFNErr;
  295.         while(err == dupFNErr)
  296.         {
  297.             err = FSpCreate(&newDocument, 'FSNP', 'FSNP', iuSystemScript);
  298.             if(err == dupFNErr)
  299.             {
  300.                 MakeAnotherName(&newDocument);
  301.             }
  302.         }
  303.         FailErr(err);
  304.         HCreateResFile(newDocument.vRefNum, newDocument.parID, newDocument.name);
  305.         FailResError();
  306.         refNum = FSpOpenResFile(&newDocument, fsRdWrPerm);
  307.         fileOpen = true;
  308.     
  309.         SaveWindowsAndPositions();
  310.  
  311.         CloseResFile(refNum);
  312.         FailResError();
  313.         fileOpen = false;
  314.     }
  315.     Catch(err)
  316.     {
  317.         if(fileOpen)
  318.             CloseResFile(refNum);
  319.     }
  320.     
  321.     //
  322.     // Once we do that, we quit
  323.     //
  324.     gApplicationShouldQuit = true;
  325.     
  326.     return noErr;
  327. } // OpenApplicationEvent
  328.  
  329. //----------------------------------------------------------------------------------------
  330. // OpenDocumentEvent: 
  331. //----------------------------------------------------------------------------------------
  332. pascal OSErr OpenDocumentEvent(TAEvent& ae, TAEvent& reply, long refCon)
  333. {
  334.     TDescriptor documentList;
  335.     TDescriptor oneDocument;
  336.     OSErr err = noErr;
  337.     FSSpec documentToOpen;
  338.     short refNum = -1;
  339.     Boolean fileOpen = false;
  340.     
  341.     Try
  342.     {
  343.         documentList = ae.GetDescriptor(keyDirectObject, typeAEList);
  344.         FOREACHDESCRIPTOR(&documentList, oneDocument)
  345.         {
  346.             oneDocument.GetFSS(documentToOpen);
  347.  
  348.             refNum = FSpOpenResFile(&documentToOpen, fsRdPerm);
  349.             fileOpen = true;
  350.             
  351.             //
  352.             // If we get an open document event, we restore all of
  353.             // the open windows and set their position again.
  354.             //
  355.             RestoreAllWindowInformation();
  356.  
  357.             CloseResFile(refNum);
  358.             fileOpen = false;
  359.         }
  360.         documentList.Dispose();
  361.     }
  362.     Catch(err)
  363.     {
  364.         if(fileOpen)
  365.             CloseResFile(refNum);
  366.  
  367.         oneDocument.Dispose();
  368.         documentList.Dispose();
  369.     }
  370.         
  371.     //
  372.     // Once we do that, we quit
  373.     //
  374.     gApplicationShouldQuit = true;    
  375.     
  376.     return noErr;
  377. } // OpenDocumentEvent
  378.